import React from 'react';
import '@testing-library/jest-dom/extend-expect';
import { render, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import Modal from './Modal';
import Title from './Title';
import Content from './Content';
import Actions from './Actions';

const TestComponent = () => {
    const [showModal, setShowModal] = React.useState(true);

    return (
        <Modal showModal={showModal} onClose={() => setShowModal(false)}>
            <Modal.Title data-testid="title">Title</Modal.Title>
            <Modal.Content data-testid="content">Content</Modal.Content>
            <Modal.Actions data-testid="actions">Actions</Modal.Actions>
        </Modal>
    );
};

test('should render Modal', () => {
    const { getByTestId } = render(
        <Modal showModal data-testid="modal"></Modal>,
    );
    const modal = getByTestId('modal');
    expect(modal).toBeInTheDocument();
});

test('should render Title', () => {
    const { getByTestId } = render(
        <Modal showModal>
            Modal<Title data-testid="title">Title</Title>
        </Modal>,
    );
    const modal = getByTestId('title');
    expect(modal).toBeInTheDocument();
});

test('should render Content', () => {
    const { getByTestId } = render(
        <Modal showModal>
            Modal<Content data-testid="content">Content</Content>
        </Modal>,
    );
    const modal = getByTestId('content');
    expect(modal).toBeInTheDocument();
});

test('should render Actions', () => {
    const { getByTestId } = render(
        <Modal showModal>
            Modal<Actions data-testid="actions">Content</Actions>
        </Modal>,
    );
    const modal = getByTestId('actions');
    expect(modal).toBeInTheDocument();
});

test('should open modal when showModal is true', () => {
    render(<Modal showModal data-testid="modal" />);
    const modal = screen.queryByTestId('modal');
    expect(modal).toBeInTheDocument();
});

test('should close modal when showModal is false', () => {
    render(<Modal showModal={false} data-testid="modal" />);
    const modal = screen.queryByTestId('modal');
    expect(modal).not.toBeInTheDocument();
});

test('should close modal when close button is clicked', () => {
    render(<TestComponent />);

    const closeButton = screen.getByRole('button');
    userEvent.click(closeButton);

    expect(screen.queryByTestId('Title')).not.toBeInTheDocument();
    expect(screen.queryByTestId('Content')).not.toBeInTheDocument();
    expect(screen.queryByTestId('Actions')).not.toBeInTheDocument();
});

test('should close modal when clicked outside the window', async () => {
    render(<TestComponent />);

    userEvent.click(document.body);

    await waitFor(() => {
        expect(screen.queryByText('Title')).not.toBeInTheDocument();
        expect(screen.queryByText('Content')).not.toBeInTheDocument();
        expect(screen.queryByText('Actions')).not.toBeInTheDocument();
    });
});

test('should close icon is displayed when displayCloseIcon prop is true', () => {
    render(
        <Modal showModal displayCloseIcon>
            <Modal.Title>Title</Modal.Title>
            <Modal.Content>Content</Modal.Content>
            <Modal.Actions>Actions</Modal.Actions>
        </Modal>,
    );

    const svgImage = screen.getByTestId('close');

    expect(svgImage).toBeInTheDocument();
});

test('should close icon is not displayed when displayCloseIcon prop is true', () => {
    render(
        <Modal showModal displayCloseIcon={false}>
            <Modal.Title>Title</Modal.Title>
            <Modal.Content>Content</Modal.Content>
            <Modal.Actions>Actions</Modal.Actions>
        </Modal>,
    );

    expect(screen.queryByRole('button')).not.toBeInTheDocument();
});

test('onClose function is called when the modal window is closed', async () => {
    const onCloseMock = jest.fn();
    render(
        <Modal showModal onClose={() => onCloseMock()}>
            <Modal.Title>Title</Modal.Title>
        </Modal>,
    );

    const closeButton = screen.getByRole('button');
    userEvent.click(closeButton);

    await waitFor(() => {
        expect(onCloseMock).toHaveBeenCalledWith();
    });
});
